/*   Copyright (C) 2011 Wolfgang Hankeln, Norma J. Wendel
 *
 *   This file is part of CDinFusion.
 *
 *   CDinFusion is free software: you can redistribute it and/or
 *   modify it under the terms of the GNU Lesser General public static 
 *   License in version 3 (LGPL3) as published by the Free Software
 *   Foundation version 3 of the License.
 *
 *   CDinFusion is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 *   Lesser General public static License for more details.
 *
 *   You should have received a copy of the Lesser General public static
 *   License along with CDinFusion; see the file COPYING. If not,
 *   write to the Free Software Foundation, 59 Temple Place - Suite 330,
 *   Boston, MA 02111-1307, USA or see <http://www.gnu.org/licenses/>.
 *   
 *   If you have any questions, send an email to: megx@mpi-bremen.de.
 */
package org.cdinfusion.data;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.io.IOUtils;
import org.cdinfusion.data.environment.Environment;
import org.cdinfusion.data.studytype.BA;
import org.cdinfusion.data.studytype.EU;
import org.cdinfusion.data.studytype.ME;
import org.cdinfusion.data.studytype.MIMARKS_C;
import org.cdinfusion.data.studytype.MIMARKS_S;
import org.cdinfusion.data.studytype.ORG;
import org.cdinfusion.data.studytype.PL;
import org.cdinfusion.data.studytype.StudyType;
import org.cdinfusion.data.studytype.VI;
import org.cdinfusion.data.util.GSCCache;
import org.cdinfusion.data.util.SingleIndexArrayComparator;
import org.springframework.util.StringUtils;

public class GetInformation {

	private static final Map<Class<? extends StudyType>, String> STUDY_TYPE_LONG_NAMES;
	static {
		final Map<Class<? extends StudyType>, String> tempStudyNames = new HashMap<Class<? extends StudyType>, String>();

		tempStudyNames.put(BA.class, "MIGSbacteria and archaea");
		tempStudyNames.put(EU.class, "MIGS eukaryotes");
		tempStudyNames.put(ME.class, "MIMS metagenome");
		tempStudyNames.put(MIMARKS_C.class, "MIMARKS culture");
		tempStudyNames.put(MIMARKS_S.class, "MIMARKS survey");
		tempStudyNames.put(ORG.class, "MIGS organelle");
		tempStudyNames.put(PL.class, "MIGS plasmid");
		tempStudyNames.put(VI.class, "MIGS virus");

		STUDY_TYPE_LONG_NAMES = Collections.unmodifiableMap(tempStudyNames);
	}
	
	public static String[][] nameInformation(Object obj) throws IOException {
		return nameInformation(obj, true);
	}

	public static String[][] nameInformation(Object obj, final boolean persistCache) throws IOException {

		if (GSCCache.containsKey(obj.getClass())) {
			return GSCCache.get(obj.getClass());
		}

		String url_part1 = "http://www.megx.net/gsc/2.1/item/";// "http://test.reno.mpi-bremen.de/gsc/2.1/item/";
		String url_part3_1 = "/label";
		URL url_1;

		final Field[] fields = obj.getClass().getDeclaredFields();
		final String[][] attributes = new String[fields.length][2];
		// 0: attributes name (shortcut), 1: attributes label (full name)

		for (int i = 0; i < fields.length; i++) {
			// name
			attributes[i][0] = fields[i].getName();

			url_1 = new URL(url_part1 + attributes[i][0] + url_part3_1);
			URLConnection connection = url_1.openConnection();
			attributes[i][1] = IOUtils.toString(connection.getInputStream())
					.trim();

		}// end for(int i = 0; i < keys.length; i++)

		Arrays.sort(attributes, new SingleIndexArrayComparator<String>(1));

		GSCCache.put(obj.getClass(), attributes);
		
		if (persistCache) {
			GSCCache.persist();
		}

		return (attributes);
	}

	public static String keyInformation(Object obj) throws IOException {
		final StringBuilder keyline = new StringBuilder(1000);
		final String[][] attributes = nameInformation(obj);
		for (int j = 0; j < attributes.length; j++) {
			keyline.append(attributes[j][1]);
			keyline.append("\t");
		}

		return keyline.toString();
	}

	public static String valueInformation(Object obj) throws IOException,
			IllegalArgumentException, SecurityException,
			IllegalAccessException, InvocationTargetException,
			NoSuchMethodException {

		final StringBuilder builder = new StringBuilder(1000);

		final String[][] data = filledFormInformation(obj);
		for (int i = 0; i < data.length; i++) {
			builder.append(data[i][2]);
			builder.append("\t");
		}

		return builder.toString();
	}

	public static String[][] filledFormInformation(Object obj)
			throws IllegalArgumentException, SecurityException,
			IllegalAccessException, InvocationTargetException,
			NoSuchMethodException, IOException {

		final String[][] attributes = nameInformation(obj);
		final String[][] result = new String[attributes.length][3];
		final Class<?> clazz = obj.getClass();
		final Class<?>[] declaredParameters = new Class<?>[0];
		for (int i = 0; i < attributes.length; i++) {
			result[i][0] = attributes[i][0];
			result[i][1] = attributes[i][1];
			final Object value = clazz.getMethod(
					"get" + StringUtils.capitalize(attributes[i][0]),
					declaredParameters).invoke(obj, (Object[]) null);
			if (value == null) {
				result[i][2] = "";
			} else {
				result[i][2] = value.toString();
			}
		}

		return result;
	}

	public static String[] gscInformation(String attribute)
			throws MalformedURLException {
		String url_part1 = "http://www.megx.net/gsc/2.1/item/";
		String[] url_part3 = { "label", "definition", "expected_value",
				"syntax", "example" };
		URL url_1;

		String line = "";
		String all = "";

		String[] info = new String[6];
		info[0] = attribute;

		for (int i = 1; i < info.length; i++) {
			url_1 = new URL(url_part1 + info[0].toString() + "/"
					+ url_part3[i - 1]);
			line = "";
			all = "";
			try {
				URLConnection connection = url_1.openConnection();
				BufferedReader br = new BufferedReader(new InputStreamReader(
						connection.getInputStream()));

				while ((line = br.readLine()) != null) {
					all = all + line.trim();
				}
				info[i] = all.trim();
			} catch (IOException exception) {
				info[i] = "";
				System.out.println("Error in gscInformation, i: " + i + " "
						+ exception.toString());
			}
			if (info[i].equals("")) {
				info[i] = "no " + url_part3[i - 1]
						+ " available in GSC database";
			}
		}// end for(int i = 0; i < fields.length; i++)

		return (info);
	}

	public static String getLongNameForStudy(final StudyType study) {
		return STUDY_TYPE_LONG_NAMES.get(study.getClass());
	}

	public static String getLongNameForEnvironment(final Environment env) {
		return env.getClass().getSimpleName().toLowerCase()
				.replaceAll("_", " ");
	}

}